package com.aiyige.utils.widget;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;

import com.aiyige.base.api.ResponseCode;
import com.aiyige.utils.ErrorUtil;
import com.aiyige.utils.RetrofitUtil;
import com.aiyige.utils.ToastX;
import com.chad.library.adapter.base.BaseQuickAdapter;

import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Response;

/**
 * Created by usera on 2017/11/22.
 */

public class LocalServerCommonDataView extends CommonDataView {
    OperationStub operationStub;
    List localDataList = new LinkedList();
    Callback callback = null;

    public LocalServerCommonDataView(@NonNull Context context) {
        super(context);
    }

    public LocalServerCommonDataView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public LocalServerCommonDataView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    public void config(BaseQuickAdapter baseQuickAdapter, RetrofitStub retrofitStub, OperationStub operationStub, Callback callback) {
        this.operationStub = operationStub;
        this.callback = callback;
        super.config(baseQuickAdapter, retrofitStub);
    }

    public void config(BaseQuickAdapter baseQuickAdapter, RetrofitStub retrofitStub, OperationStub operationStub) {
        config(baseQuickAdapter, retrofitStub, operationStub, null);
    }

    public interface OperationStub {
        List query();

        int compare(Object o1, Object o2);

        boolean equal(Object o1, Object o2);
    }

    public interface Callback {
        void onClearRequestState();
    }

    @Override
    public void requestData() {
        if (cdvRetrofitStub == null) return;
        if (operationStub == null) return;
        cdvRetrofitStub.call(page).enqueue(new retrofit2.Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                try {
                    if (response.code() != ResponseCode.OK) {
                        throw new Exception(ErrorUtil.extractMessageFromErrorResponse(response));
                    }
                    String json = RetrofitUtil.getResponseBodyAsString(response);
                    List resultList = new LinkedList<>();
                    HandleResult handleResult = cdvRetrofitStub.handleResponse(json, resultList);
                    if (handleResult.isSuccess()) {
                        if (page == 0) {
                            localDataList.clear();
                            localDataList.addAll(operationStub.query());
                            trimServerData(resultList, localDataList);
                            resultList.addAll(localDataList);
                            Collections.sort(resultList, new Comparator() {
                                @Override
                                public int compare(Object o1, Object o2) {
                                    return operationStub.compare(o1, o2);
                                }
                            });
                            cdvAdapter.setNewData(resultList);
                        } else {
                            trimServerData(resultList, localDataList);
                            cdvAdapter.addData(resultList);
                        }
                        lastPage = handleResult.isLastPage();
                        if (!lastPage) {
                            cdvAdapter.loadMoreComplete();
                        } else {
                            cdvAdapter.loadMoreEnd(autoHideFooter && (page == 0));
                        }
                        page++;
                        hideCoverLayout();
                        clearRequestState();
                    } else {
                        throw new Exception(handleResult.getMessage());
                    }
                } catch (Exception e) {
                    if (errorHandler != null) {
                        errorHandler.onResponseError(e.getMessage());
                    }
                    onFailure(call, null);
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                if (t != null) {
                    if (errorHandler != null) {
                        errorHandler.onNetError(t.getMessage());
                    }
                }
                //ToastX.show(getContext(), t.getMessage());
                if (page == 0) {
                    showErrorLayout();
                } else {
                    cdvAdapter.loadMoreFail();
                }
                clearRequestState();
            }
        });
    }

    @Override
    public void clearRequestState() {
        super.clearRequestState();
        if (callback != null) {
            callback.onClearRequestState();
        }
    }

    private void trimServerData(List serverDataList, List localDataList) {
        outerLoop:
        for (Object localData : localDataList) {
            Iterator serverDataIterator = serverDataList.iterator();
            while (serverDataIterator.hasNext()) {
                Object adapterData = serverDataIterator.next();
                if (operationStub.equal(adapterData, localData)) {
                    serverDataIterator.remove();
                    continue outerLoop;
                }
            }
        }
    }
}
